package source;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.NoSuchElementException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Scanner;

/**
 *
 * @author Sabitov Artem
 */
public class mpClient {
	// переменные отвечающие за структуру сервера
	private ArrayList<String> BodyFile = new ArrayList<>();
	private ArrayList<String> HeadFile = new ArrayList<>();
	private ArrayList<String> Crew = new ArrayList<>();
	private ArrayList<String> Vessel = new ArrayList<>();
	private HashMap<String, ArrayList<String>> CrewSection = new HashMap<>();
	private HashMap<String, ArrayList<String>> VesselSection = new HashMap<>();
	private int	iCrewCounter;
	private int iVesselCounter;
	// общие переменные класса
	private int iClientID;
	private String sClientPath;
	private boolean bEndFile;
	private mpServer objServer;
	
    mpClient(int iArgClientID, String sArgClientPath, mpServer objArgServer) {
		iClientID = iArgClientID;
		sClientPath = sArgClientPath;
		objServer = objArgServer;
		buildClient(false);
	}
	
	public void updateClient() {
		buildClient(true);
		objServer.syncServer(iClientID, CrewSection, VesselSection);
	}
	
	public void syncClient(HashMap serverCrews, HashMap serverVessels) {
		CrewSection = mpSync.syncCrews(CrewSection, serverCrews, false);
		VesselSection = mpSync.syncVessels(VesselSection, serverVessels, false);
		saveClient();
	}
	
	private void buildClient(boolean bReBuild) {
		BodyFile.clear();
		HeadFile.clear();
		bEndFile = false;
		log("");
		if(bReBuild) {
			//objLog("update client.");
		} else {
			objLog("build client.");
		}
		// заполняем структуры, собираем объект
		try {
			Scanner sc = new Scanner(new File(sClientPath));
			String sNextLine;
			Object oObj;
			// читаем все содержимое файла
			// заполняем счетчики кораблей, экипажей
			do {
				try {
					sNextLine = sc.nextLine();
					BodyFile.add(sNextLine);
					switch (sNextLine) {
						case mpPattern.CREW:
							iCrewCounter++;
							break;
						case mpPattern.VESSEL:
							iVesselCounter++;
							break;
					}
				} catch (NoSuchElementException ex) {
					log(this.toString() + " file: " + sClientPath + " read succesfully.");
					bEndFile = true;
				}
			} while (!bEndFile);
			// заполняем структуры объекта файла-клиента
			int iCrewIndex = 0;
			int iVesselIndex = 0;
			for (Iterator it = BodyFile.iterator(); it.hasNext();) {
				oObj = it.next();
				switch (oObj.toString()) {
					// нашли экипаж
					case mpPattern.CREW:
						// добавляем секцию экипажа в строрайдж
						buildSection(oObj, Crew, it);
						CrewSection.put(Crew.get(2), Crew);
						Crew = new ArrayList<>();
						iCrewIndex++;
						break;
					// нашли корабль
					case mpPattern.VESSEL:
						// добавляем секцию корабля в строрайдж
						buildSection(oObj, Vessel, it);
						VesselSection.put(Vessel.get(2), Vessel);
						Vessel = new ArrayList<>();
						iVesselIndex++;
						break;
					// все остальное кидаем в заголовок
					default:
						HeadFile.add(oObj.toString());
						break;
				}
			}
			// удалим последние скобки
			HeadFile.remove(HeadFile.size() - 1);
			HeadFile.remove(HeadFile.size() - 1);
			sc.close();
		// обработка исключения	
		} catch (FileNotFoundException ex) {
			log("class: " + mpServer.class.getName() + " file: " + sClientPath + " read failure.");
		}
		//objLog("building client succesfully..");
	}
	
	// собирает секцию для сторайджа
	private ArrayList<String> buildSection(Object oObj, ArrayList<String> List, Iterator it) {
		List.add(oObj.toString());
		int iBraceCount = 0;
		do {
			oObj = it.next();
			switch (oObj.toString().trim()) {
				case "{":
					List.add(oObj.toString());
					iBraceCount++;
					break;
				case "}":
					List.add(oObj.toString());
					iBraceCount--;
					break;
				default:
					List.add(oObj.toString());
					break;
			}
		} while (iBraceCount != 0);
		return List;
	}
	
	public void saveClient() {	
        PrintWriter pw;
		try {
			if(mpMain.bDebug) {
				pw = new PrintWriter(sClientPath+".out");
			} else {
				pw = new PrintWriter(sClientPath);
			}
			for (Iterator it = HeadFile.iterator(); it.hasNext();) {
				pw.println(it.next().toString());
			}
			Collection allKey = CrewSection.keySet();
			for(Iterator i = allKey.iterator(); i.hasNext();) {
				ArrayList listTemp = CrewSection.get(i.next());
				for(Iterator j = listTemp.iterator(); j.hasNext();) {
					pw.println(j.next().toString());
				}
			}
			allKey = VesselSection.keySet();
			for(Iterator i = allKey.iterator(); i.hasNext();) {
				ArrayList listTemp = VesselSection.get(i.next());
				for(Iterator j = listTemp.iterator(); j.hasNext();) {
					pw.println(j.next().toString());
				}
			}
			pw.println("	}");
			pw.println("}");
			pw.close();
			objLog("save persistent.sfs.");
		} catch (FileNotFoundException ex) {};
	}
	
	public String getClientPath() {
		return sClientPath;
	}
	
	public int getClientID() {
		return iClientID;
	}
	
	// дебаг
	public void log(Object oObj) {
		mpLog.dbgLog(oObj);
	}
	// лог
	public void objLog(Object oObj) {
		mpLog.objLog(this, oObj + " ID:" + iClientID);
	}
}
